.model small,c    
.586p
.data
;
;  Descriptor Access Rights Definitions
;
PRESENT			EQU	080H		; 1 = Descriptor is available
SEGMENT_DESC		EQU	010H		; 1 = Segment Descriptor
EXECUTABLE		EQU	008H		; 1 = Data desc. is executable
CODE_CONFORMING		EQU	004H		; 1 = Code desc. is conforming
DATA_EXPAND_DOWN	EQU	004H		; 1 = Data desc. limit is diff.
CODE_READABLE		EQU	002H		; 1 = Code desc. is readable
DATA_WRITEABLE		EQU	002H		; 1 = Data desc. is writable
TASK_BUSY		EQU	002H		; 1 = Task is set busy
ACCESSED		EQU	001H		; 1 = Segment has been accessed

DEFAULT_DRIGHTS EQU	PRESENT + SEGMENT_DESC + DATA_WRITEABLE + ACCESSED
DEFAULT_CRIGHTS EQU	PRESENT + SEGMENT_DESC + EXECUTABLE + CODE_READABLE + ACCESSED

POD_DRIGHTS	EQU	PRESENT + SEGMENT_DESC + DATA_WRITEABLE + ACCESSED
POD_CRIGHTS	EQU	PRESENT + SEGMENT_DESC + EXECUTABLE + CODE_READABLE + ACCESSED
POD_SRIGHTS	EQU	PRESENT + SEGMENT_DESC + DATA_WRITEABLE + ACCESSED

SegDescriptor	STRUC
  DescLimit		DW	0000		; Segment Limit byte field
  DescBaseLo		DW	0000		; Segment base address (15-0)
  DescBaseHi		DB	00		; Segment base address (23-16)
  DescAccess		DB	00		; Access Rights byte
  DescLimit386		DB	00		; Extended Limit (386/486)
  DescBase386		DB	00		; Extended Base (386/486)
SegDescriptor	ENDS



SETDS                   EQU     001H
SETES                   EQU     002H
SETFS                   EQU     004H
SETGS                   EQU     008H
SETCS                   EQU     010H
SETSS                   EQU     020H
.code



;---------------------------------------------------------------------
;arg1:     refer to PODGDTStart table. select which segment descriptor. 
;arg2:     1 --    ds
;          2 --    es
;          4 --    fs
;          8 --    gs
;          16 --   cs
;          32 --   ss
;purpose: set segment descriptor cache to required attribute.
 coreSetLimits PROC NEAR C  PUBLIC uses eax bx dx  si , arg1:word , arg2:word
	cli				; (1) Disable maskable hardware interrupts
	cld				; Initialize direction flag forward
        
	;enable a20
	mov     al, 2
	out     92h, al
	; calculate GDT table address.
        xor     eax , eax
	push    cs
	pop     dx
	movzx   eax , dx
	shl     eax , 4
	add     eax , offset PODGDTStart


	mov     word ptr cs:ROMGDTAddress + 2 , ax
	shr     eax , 16
	mov     word ptr cs:ROMGDTAddress + 4 ,ax

	mov	edx, offset ROMGDTAddress ; Get ROM GDT address
	mov     si, dx
	lgdt	FWORD PTR cs:[si]	; (2) Load the GDT descriptor , 
	                                ;     GDTR contains physical memory address of GDT.

	mov	eax, CR0		; Get CPU control word 0
	or	al, 01			; Enable CPU protected mode
	mov	CR0, eax		; (3) Write back to CPU control word 0
	jmp	queueFlush1		; (4) Flush , change the flow of execution & serializes the processor.

queueFlush1:
        mov     bx, arg1
        mov     ax, arg2

	.if( ax & SETDS )               ;(5)
	     mov	ds, bx			; Set DS
	.endif

	.if( ax & SETES )
	     mov	es, bx			; Set ES     
        .endif 

	.if( ax & SETFS )
	     mov	fs, bx			; Set FS
	.endif
   
        .if( ax & SETGS )
	     mov	gs, bx			; Set GS
	.endif     	
	

	;  ...... cs , ss not ready.
	;

;	mov     si, ss
;	mov     bx, COREPD_SMALL
;	mov     ss, bx  

	mov	eax, CR0		; Get CPU control word 0
	and	al, 0FEh		; Disable CPU protected mode
	mov	CR0, eax		; (6) Write back to CPU control word 0
;	JMPF	BCG, queueFlush2	; Flush (this must be a far jump)
        jmp     far ptr queueFlush2     ; (7) must far jump
queueFlush2:
	xor	bx, bx	
        mov     ax, arg2

	.if( ax & SETDS )               
	     mov	ds, bx			; Set DS
	.endif

	.if( ax & SETES )
	     mov	es, bx			; Set ES     
        .endif 

	.if( ax & SETFS )
	     mov	fs, bx			; Set FS
	.endif
   
        .if( ax & SETGS )
	     mov	gs, bx			; Set GS
	.endif  
;	mov     ss, si

	sti                             ; (8) enable maskable hardware interrupt 
	
	ret
coreSetLimits  ENDP


;SegDescriptor	STRUC
;  DescLimit		DW	0000		; Segment Limit byte field(15-0)
;  DescBaseLo		DW	0000		; Segment base address (15-0)
;  DescBaseHi		DB	00		; Segment base address (23-16)
;  DescAccess		DB	00		; Access Rights byte
;                       bit  0-3     ;type      Segment type
;                       bit  4       ;s         Descriptor type (0 = system; 1 = code or data)
;                       bit  5-6     ;DPL       Descriptor privilege level
;                       bit  7       ;P         Segment present
;  DescLimit386		DB	00		; Extended Limit (386/486)
;                       bit 0-3      ;Segment Limit (19:16)
;                       bit 4        ;AVL  Available for use by system software
;                       bit 5        ;0    
;                       bit 6        ;D/B  Default operation size (0 = 16-bit segment; 1 = 32-bit segment)
;                       bit 7        ;G    Granularity (1 = 4K byte unit ; 0 =  byte)
;  DescBase386		DB	00		; Extended Base (386/486) (31-24)
;SegDescriptor	ENDS


PODGDTStart	LABEL	BYTE

	PUBLIC	COREPD_GDT
COREPD_GDT	EQU	000h			; GDT descriptor
 SegDescriptor	<00, 00, 00, 00, 00h, 00h>

	PUBLIC	COREPD_BIG
COREPD_BIG	EQU	08h			; Working huge descriptor ( 0 ~ 4G )
 SegDescriptor	<0FFFFh, 0000h, 00h, POD_DRIGHTS, 8Fh, 00h>

	PUBLIC	COREPD_SMALL
COREPD_SMALL EQU	010h			; Working small descriptor ( 0 ~ 64K )
 SegDescriptor	<0FFFFh, 0000h, 00h, POD_DRIGHTS, 00h, 00h>

	PUBLIC	COREPD_BIG_STACK
COREPD_BIG_STACK EQU	18h			; Working huge descriptor ( 0 ~ 4G ,32-bit segment )
 SegDescriptor	<0FFFFh, 0000h, 00h, POD_DRIGHTS, 0CFh, 00h>


PODGDTLength	EQU	($ - PODGDTStart) - 1

	PUBLIC	ROMGDTAddress
ROMGDTAddress LABEL WORD
	DW	PODGDTLength			; The length of the GDT

;	PUBLIC	linearGdtRelocate		; Make accessible to bios
;	ALIAS4C	linearGdtRelocate		; Make accessible to build
linearGdtRelocate LABEL DWORD
	DW	00              		; The 32-bit physical address
	DW	00				; of the GDT                                                   

;
;C Prototype
;BYTE readPortBYTE (WORD portIndex)
;{
;}
;
readPortBYTE proc near public uses dx ,portIndex:word
     mov   dx , portIndex
     in    al , dx
  
     ret
readPortBYTE endp


;C Prototype
;WORD readPortWORD (WORD portIndex)
;{
;}
;
readPortWORD proc near public uses dx ,portIndex:word
     mov   dx , portIndex
     in    ax , dx
  
     ret
readPortWORD endp

;C Prototype
;DWORD readPortDWORD (WORD portIndex)
;{
;}
;
readPortDWORD proc near public ,portIndex:word
     mov   dx , portIndex
     in    eax , dx
    
     ror   eax , 16
     mov   dx , ax
     ror   eax , 16
     
     ret
readPortDWORD endp

;C Prototype
;void writePortBYTE (WORD portIndex, BYTE value)
;{
;}
;
writePortBYTE proc near public uses dx ax , portIndex:word, value:byte
     mov   dx, portIndex
     mov   al, value
     out   dx, al
     ret
writePortBYTE endp


;C Prototype
;void writePortWORD (WORD portIndex, WORD value)
;{
;}
;
writePortWORD proc near public uses dx ax , portIndex:word, value:word
     mov   dx, portIndex
     mov   ax, value
     out   dx, ax
     ret
writePortWORD endp


;C Prototype
;void writePortDWORD (WORD portIndex, DWORD value)
;{
;}
;
writePortDWORD proc near public uses dx eax , portIndex:word, value:dword
     mov   dx, portIndex
     mov   eax, value
     out   dx, eax
     ret
writePortDWORD endp




;
;
;note: gs base address is 0, limit is 4G.
writeMemDWORD proc near public uses esi , MemAddress:dword, Value:dword
	mov  eax, MemAddress
	mov  esi, eax
	mov  eax, Value
	mov  dword ptr gs:[esi], eax	
	ret
writeMemDWORD  endp


;
;
;note: gs base address is 0, limit is 4G.
getMemDWORD proc near public uses esi,MemAddress:dword
	mov  eax, MemAddress
	mov  esi, eax
	mov  eax, dword ptr gs:[esi]
	ror  eax, 16
	mov  dx,  ax
	ror  eax, 16
	ret

getMemDWORD endp

;note: gs base address is 0, limit is 4G.
getMMIODWORD proc near public uses esi,MemAddress:dword
	JMP	$;;;;;;ADAM
	mov  eax, MemAddress
	call	print32;;;;;;;temp
	mov  esi, eax
	mov  eax, dword ptr gs:[esi]
	call	print32;;;;;;temp
	ror  eax, 16
	mov  dx,  ax
	ror  eax, 16
	ret

getMMIODWORD endp

;
;
;note: gs base address is 0, limit is 4G.
setMemDWORD proc near public uses esi,MemAddress:dword, AndValue:dword, OrValue:dword	
	mov	eax, MemAddress
	mov	esi, eax
	mov	eax, gs:[esi]
	and	eax, AndValue
	or	eax, OrValue
	mov	gs:[esi], eax
	
	ret
setMemDWORD endp

include print.inc
end
